package com.hj.dapp.config.security;

import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hj.dapp.business.role.model.Role;
import com.hj.dapp.business.user.model.User;
import com.hj.dapp.common.resp.RestResp;
import com.hj.dapp.common.util.JwtUtil;
import com.hj.dapp.common.util.RsaUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.hj.dapp.config.exp.BusinessErrorEnum.USER_EXCEPTION;

/**
 * @author 胡奥程
 * @version 1.0
 * @date 2023/12/29
 */
public class JwtLoginFilter extends AbstractAuthenticationProcessingFilter {

    private AuthenticationManager authenticationManager;

    public JwtLoginFilter(AuthenticationManager authenticationManager) {
        super(new AntPathRequestMatcher("/user/login",
                "POST"));
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            ServletInputStream  in = request.getInputStream();
            String body = IOUtils.toString(in, StandardCharsets.UTF_8);
            User user = JSON.parseObject(body, User.class);
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
        } catch (Exception e) {
            try {
                e.printStackTrace();
                response.setContentType("application/json;charset=utf-8");
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                PrintWriter   out = response.getWriter();
                out.write(new ObjectMapper().writeValueAsString(RestResp.error(USER_EXCEPTION)));
                out.flush();
                out.close();
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }

        }
        return null;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);
        PrintWriter out = response.getWriter();
        Map<String,String> map = new HashMap<>(4);
        User user = new User();
        user.setUsername(authResult.getName());
        user.setRoles((List<Role>) authResult.getAuthorities());
        map.put("token", JwtUtil.generateTokenExpireInMillis(user, RsaUtils.getPrivateKey()));
        out.write(new ObjectMapper().writeValueAsString(RestResp.ok(map)));
        out.flush();
        out.close();

    }
}
